﻿#include "videolayoutwidget.h"
#include <QAction>
#include <QGridLayout>
#include <QListWidgetItem>
#include <QMenu>
#include <QMimeData>
#include <QResizeEvent>
#include "globaltools.h"
#include "videowindow.h"

#define VIDEO_TIMER_INTERVAL 200
#define ID_ROLE Qt::UserRole
#define MIC_ROLE Qt::UserRole+1
#define NAME_ROLE Qt::UserRole+2

#define margin 2
#define spacing 2

VideoLayoutWidget::VideoLayoutWidget(QWidget *parent) : QWidget(parent),
    mode(0), row(0), column(0)
{
}

void VideoLayoutWidget::getConfig(qint8 &mode, int &row, int &column)
{
    mode = this->mode;
    row = this->row;
    column = this->column;
}

static inline QString getName(const QMap<qint64, QListWidgetItem *> &userListItems, qint64 user_id)
{
    QString name;
    if(auto item = userListItems.value(user_id, Q_NULLPTR))
    {
        name = item->data(NAME_ROLE).toString();
        if(name.isEmpty())
            name = item->text();
    }
    if(name.isEmpty())
        name = QString::number(user_id);
    return name;
}

void VideoLayoutWidget::handle_mic_state(const QMap<int, qint64> &mic_list, const QMap<qint64, QListWidgetItem *> &userItems)
{
    QList<int> mic_ids = mic_list.keys();
    bool hasChanged = false;
    QList<VideoWindow*> toDelete;
    QMap<int, VideoWindow*> newMapping;

    for(auto it_video = videos.begin(); it_video != videos.end();)
    {
        auto window = *it_video;
        if(mic_ids.removeOne(window->id))
        {
            newMapping[window->id] = window;
            it_video++;
        }
        else {
            //空闲后应该释放
            window->hide();
            toDelete.append(window);
            it_video = videos.erase(it_video);
            hasChanged = true;
        }
    }
    //mic_ids中已经去除已经有视频的mic_id
    for (auto it_key = mic_ids.constBegin(); it_key != mic_ids.constEnd(); it_key++) {
        qint64 uid = mic_list[*it_key];
        if(uid > 0)
        {
            VideoWindow* window = Q_NULLPTR;
            if(!toDelete.isEmpty())
                window = toDelete.takeFirst();
            if(!window)
                window = new VideoWindow(this);
            window->setId(*it_key, uid, getName(userItems, uid));
            videos.append(window);
            hasChanged = true;
            newMapping[window->id] = window;
            window->show();
        }
    }

    setHidden(videos.isEmpty());
    if(!hasChanged)
        return;

    doChange();

    videoMapping.swap(newMapping);
    qDeleteAll(toDelete);

    if(videos.isEmpty())
        timer.stop();
    else if(!timer.isActive())
        timer.start(VIDEO_TIMER_INTERVAL,this);
}

void VideoLayoutWidget::handle_video(int micid, const QPixmap &pix)
{
    if(auto window = videoMapping.value(micid, Q_NULLPTR))
        window->handleVideo(pix);
}

void VideoLayoutWidget::handle_volume(int micid, int volume)
{
    if(auto window = videoMapping.value(micid, Q_NULLPTR))
        window->handle_volume(volume);
}

QSize VideoLayoutWidget::sizeHint() const
{
    return QSize(QWIDGETSIZE_MAX, 400);
}

void VideoLayoutWidget::resizeEvent(QResizeEvent *e)
{
    doLayout(e->size());
}

void VideoLayoutWidget::timerEvent(QTimerEvent *e)
{
    if(e->timerId() == timer.timerId())
    {
        for(auto it = videoMapping.constBegin(); it != videoMapping.constEnd(); it++)
        {
            if(auto window = it.value())
                window->handle_timer_event();
        }
    }
    QWidget::timerEvent(e);
}

void VideoLayoutWidget::contextMenuEvent(QContextMenuEvent *e)
{
    if(auto child = qobject_cast<VideoWindow*>(childAt(e->pos())))
    {
        if(child->tryContextMenu(e, parentWidget()->parentWidget()->parentWidget()->parentWidget()))
            return;
    }
    //空白处
}

void VideoLayoutWidget::doChange()
{
    int videoCount = videos.size();
    if(videoCount <= 0)
    {
        row = column = 0;
    }
    if(videoCount <= 3)
    {
        row = 1;
        column = videoCount;
    }
    else if (videoCount) {
        const int max_column = 5;
        row = (videoCount + max_column - 1) / max_column;
        column = (videoCount + row - 1) / row;
    }
    doLayout(size());
}

void VideoLayoutWidget::doLayout(const QSize &size)
{
    if(column < 1 || row < 1)
        return;
    int availableTotalWidth = size.width() - (column - 1) * spacing - margin * 2;
    int availableTotalHeight = size.height() - (row - 1) * spacing - margin * 2;

    int availablePerWidth = availableTotalWidth / column;
    int availablePerHeight = availableTotalHeight / row;

    QRect availablePerRect(0, 0, availablePerWidth, availablePerHeight);
    int index = 0;
    for(int r = 0; r < row; r++)
    {
        for(int c = 0; c < column; c++)
        {
            if(index >= videos.size())
                return;
            availablePerRect.moveTo(margin + c * (availablePerWidth + spacing), margin + r * (availablePerHeight + spacing));
            videos[index++]->setGeometry(availablePerRect);
        }
    }
}

